/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/container
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AETArray.h
// Author:		Gianluca Belardelli
// Date:		18/04/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AETARRAY_H_
#define _AETARRAY_H_

template <typename T, typename Allocator=AEContainerHeapAllocator>
class AETArray : public AETBaseArray<T>
{
// Members
public:
	typedef Allocator AEAllocatorType;
	//friend class hkArrayUtil;

	typedef AETArray<T,AEContainerTempAllocator> arrTemp;
	typedef AETArray<T,AEContainerDebugAllocator> arrDebug;
	typedef AETArray<T,AEContainerHeapAllocator> arrHeap;

// Methods
protected:
	/// Not publicly accessible, too easy to call accidentally.
	AE_FORCEINLINE AETArray( const AETArray &refArray );

public:
	AE_FORCEINLINE AETArray( void ) : AETBaseArray<T>() {}

	///
	AE_FORCEINLINE ~AETArray( void );

	/// Creates an array of size n. All elements are uninitialized.
	explicit AE_FORCEINLINE AETArray( AEINT32 nSize );

	/// Creates an array of n elements initialized to 'fill'.
	AE_FORCEINLINE AETArray( AEINT32 nSize, const T &tFill );

	/// Noncopying initialization from an existing external buffer.
	/// This does not copy the array but uses it in place until its capacity
	/// is exceeded at which point a reallocation occurs and the array behaves
	/// like a normal hkArray.
	/// The caller must ensure that the buffer is valid for the lifetime
	/// of this array and for deallocation of the buffer.
	AE_FORCEINLINE AETArray( T *lpBuffer, AEINT32 nSize, AEINT32 nCapacity ) : AETBaseArray<T>( lpBuffer, nSize, nCapacity ) {}

	/// Copy another array
	AE_FORCEINLINE AETArray &operator= ( const AETBaseArray<T> &refArray );
	AE_FORCEINLINE AETArray &operator= ( const AETArray &refArray );

	/// Swaps this array's internal storage with 'a'.
	void Swap( AETArray &refArray );

	AE_FORCEINLINE void ClearAndDeallocate( void );
	AE_FORCEINLINE void OptimizeCapacity( AEINT32 nNumFreeElemsLeft, AEBOOL32 bShrinkExact=0 );
	AE_FORCEINLINE void PushBack( const T &tElem );
	AE_FORCEINLINE AEUINT32 Reserve( AEINT32 nSize );
	AE_FORCEINLINE AEUINT32 ReserveExactly( AEINT32 nSize );
	AE_FORCEINLINE void SetSize( AEINT32 nSize );
	AE_FORCEINLINE void SetSize( AEINT32 nSize, const T &tFill );
	AE_FORCEINLINE AEUINT32 TrySetSize( AEINT32 nSize );
	AE_FORCEINLINE T &ExpandOne( void );
	AE_FORCEINLINE T *ExpandBy( AEINT32 nSize );
	AE_FORCEINLINE T *ExpandAt( AEINT32 nIndex, AEINT32 nNumToInsert );
	AE_FORCEINLINE void InsertAt( AEINT32 nIndex, const T &tElem );
	AE_FORCEINLINE void InsertAt( AEINT32 nIndex, const T *lpArray, AEINT32 nNumElems );
	AE_FORCEINLINE void Append( const T *lpArray, AEINT32 nNumElems );
	AE_FORCEINLINE void SpliceInto( AEINT32 nIndex, AEINT32 nDel, const T *lpArray, AEINT32 nNumElems );
		
	template <typename K>
	AE_FORCEINLINE void Append( const AETBaseArray<K> &tArray)  { Append( tArray.Begin(), tArray.GetSize() ); }

	/*
	AE_FORCEINLINE void ClearAndDeallocate( void ) { AETBaseArray<T>::ClearAndDeallocate( AEAllocatorType().Get( this ) ); }
	AE_FORCEINLINE void OptimizeCapacity( AEINT32 nNumFreeElemsLeft, AEBOOL32 bShrinkExact=0 ) { AETBaseArray<T>::OptimizeCapacity( AEAllocatorType().Get( this ), nNumFreeElemsLeft, bShrinkExact ); }
	AE_FORCEINLINE void PushBack( const T &tElem ) { AETBaseArray<T>::PushBack( AEAllocatorType().Get( this ), tElem ); }
	AE_FORCEINLINE AEUINT32 Reserve( AEINT32 nSize ) { return AETBaseArray<T>::Reserve( AEAllocatorType().Get( this ), nSize ); }
	AE_FORCEINLINE AEUINT32 ReserveExactly( AEINT32 nSize ) { return AETBaseArray<T>::ReserveExactly( AEAllocatorType().Get( this ), nSize ); }
	AE_FORCEINLINE void SetSize( AEINT32 nSize ) { AETBaseArray<T>::SetSize( AEAllocatorType().Get( this ), nSize ); }
	AE_FORCEINLINE void SetSize( AEINT32 nSize, const T &tFill ) { AETBaseArray<T>::SetSize( AEAllocatorType().Get( this ), nSize, tFill ); }
	AE_FORCEINLINE AEUINT32 TrySetSize( AEINT32 nSize ) { return AETBaseArray<T>::TrySetSize( AEAllocatorType().Get( this ), nSize ); }
	AE_FORCEINLINE T &ExpandOne( void ) { return AETBaseArray<T>::ExpandOne( AEAllocatorType().Get( this ) ); }
	AE_FORCEINLINE T *ExpandBy( AEINT32 nSize ) { return AETBaseArray<T>::ExpandBy( AEAllocatorType().Get( this ), nSize ); }
	AE_FORCEINLINE T *ExpandAt( AEINT32 nIndex, AEINT32 nNumToInsert ) { return AETBaseArray<T>::ExpandAt( AEAllocatorType().Get( this ), nIndex, nNumToInsert ); }
	AE_FORCEINLINE void InsertAt( AEINT32 nIndex, const T &tElem ) { AETBaseArray<T>::InsertAt( AEAllocatorType().Get( this ), nIndex, tElem ); }
	AE_FORCEINLINE void InsertAt( AEINT32 nIndex, const T *lpArray, AEINT32 nNumElems ) { AETBaseArray<T>::InsertAt( AEAllocatorType().Get( this ), nIndex, lpArray, nNumElems ); }
	AE_FORCEINLINE void Append( const T *lpArray, AEINT32 nNumElems ) { AETBaseArray<T>::Append( AEAllocatorType().Get( this ), lpArray, nNumElems ); }
	AE_FORCEINLINE void SpliceInto( AEINT32 nIndex, AEINT32 nDel, const T *lpArray, AEINT32 nNumElems ) { return AETBaseArray<T>::SpliceInto( AEAllocatorType().Get( this ), nIndex, nDel, lpArray, nNumElems ); }		

	template <typename K>
	AE_FORCEINLINE void Append( const AETBaseArray<K> &tArray) { Append( tArray.Begin(), tArray.GetSize() ); }
	*/
};

#include "AETArray.inl"

#endif // _AETARRAY_H_
